summaryrefslogtreecommitdiffstats
path: root/src/audio_core/renderer/adsp/audio_renderer.h
blob: 02e923c842051d7e43fb484794cca024d42a5ef6 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#pragma once

#include <array>
#include <memory>
#include <thread>

#include "audio_core/renderer/adsp/command_buffer.h"
#include "audio_core/renderer/adsp/command_list_processor.h"
#include "common/common_types.h"
#include "common/reader_writer_queue.h"
#include "common/thread.h"

namespace Core {
namespace Timing {
struct EventType;
}
class System;
} // namespace Core

namespace AudioCore {
namespace Sink {
class Sink;
}

namespace AudioRenderer::ADSP {

enum class RenderMessage {
    /* 0x00 */ Invalid,
    /* 0x01 */ AudioRenderer_MapUnmap_Map,
    /* 0x02 */ AudioRenderer_MapUnmap_MapResponse,
    /* 0x03 */ AudioRenderer_MapUnmap_Unmap,
    /* 0x04 */ AudioRenderer_MapUnmap_UnmapResponse,
    /* 0x05 */ AudioRenderer_MapUnmap_InvalidateCache,
    /* 0x06 */ AudioRenderer_MapUnmap_InvalidateCacheResponse,
    /* 0x07 */ AudioRenderer_MapUnmap_Shutdown,
    /* 0x08 */ AudioRenderer_MapUnmap_ShutdownResponse,
    /* 0x16 */ AudioRenderer_InitializeOK = 0x16,
    /* 0x20 */ AudioRenderer_RenderResponse = 0x20,
    /* 0x2A */ AudioRenderer_Render = 0x2A,
    /* 0x34 */ AudioRenderer_Shutdown = 0x34,
};

/**
 * A mailbox for the AudioRenderer, allowing communication between the host and the AudioRenderer
 * running on the ADSP.
 */
class AudioRenderer_Mailbox {
public:
    /**
     * Send a message from the host to the AudioRenderer.
     *
     * @param message - The message to send to the AudioRenderer.
     */
    void HostSendMessage(RenderMessage message);

    /**
     * Host wait for a message from the AudioRenderer.
     *
     * @return The message returned from the AudioRenderer.
     */
    RenderMessage HostWaitMessage();

    /**
     * Send a message from the AudioRenderer to the host.
     *
     * @param message - The message to send to the host.
     */
    void ADSPSendMessage(RenderMessage message);

    /**
     * AudioRenderer wait for a message from the host.
     *
     * @return The message returned from the AudioRenderer.
     */
    RenderMessage ADSPWaitMessage();

    /**
     * Get the command buffer with the given session id (0 or 1).
     *
     * @param session_id - The session id to get (0 or 1).
     * @return The command buffer.
     */
    CommandBuffer& GetCommandBuffer(s32 session_id);

    /**
     * Set the command buffer with the given session id (0 or 1).
     *
     * @param session_id - The session id to get (0 or 1).
     * @param buffer     - The command buffer to set.
     */
    void SetCommandBuffer(u32 session_id, const CommandBuffer& buffer);

    /**
     * Get the total render time taken for the last command lists sent.
     *
     * @return Total render time taken for the last command lists.
     */
    u64 GetRenderTimeTaken() const;

    /**
     * Get the tick the AudioRenderer was signalled.
     *
     * @return The tick the AudioRenderer was signalled.
     */
    u64 GetSignalledTick() const;

    /**
     * Set the tick the AudioRenderer was signalled.
     *
     * @param tick - The tick the AudioRenderer was signalled.
     */
    void SetSignalledTick(u64 tick);

    /**
     * Clear the remaining command count.
     *
     * @param session_id - Index for which command list to clear (0 or 1).
     */
    void ClearRemainCount(u32 session_id);

    /**
     * Get the remaining command count for a given command list.
     *
     * @param session_id - Index for which command list to clear (0 or 1).
     * @return The remaining command count.
     */
    u32 GetRemainCommandCount(u32 session_id) const;

    /**
     * Clear the command buffers (does not clear the time taken or the remaining command count).
     */
    void ClearCommandBuffers();

private:
    /// Host signalling event
    Common::Event host_event{};
    /// AudioRenderer signalling event
    Common::Event adsp_event{};
    /// Host message queue

    Common::ReaderWriterQueue<RenderMessage> host_messages{};
    /// AudioRenderer message queue

    Common::ReaderWriterQueue<RenderMessage> adsp_messages{};
    /// Command buffers

    std::array<CommandBuffer, MaxRendererSessions> command_buffers{};
    /// Tick the AudioRnederer was signalled
    u64 signalled_tick{};
};

/**
 * The AudioRenderer application running on the ADSP.
 */
class AudioRenderer {
public:
    explicit AudioRenderer(Core::System& system);
    ~AudioRenderer();

    /**
     * Start the AudioRenderer.
     *
     * @param mailbox The mailbox to use for this session.
     */
    void Start(AudioRenderer_Mailbox* mailbox);

    /**
     * Stop the AudioRenderer.
     */
    void Stop();

private:
    /**
     * Main AudioRenderer thread, responsible for processing the command lists.
     */
    void ThreadFunc();

    /**
     * Creates the streams which will receive the processed samples.
     */
    void CreateSinkStreams();

    /// Core system
    Core::System& system;
    /// Main thread
    std::thread thread{};
    /// The current state
    std::atomic<bool> running{};
    /// The active mailbox
    AudioRenderer_Mailbox* mailbox{};
    /// The command lists to process
    std::array<CommandListProcessor, MaxRendererSessions> command_list_processors{};
    /// The output sink the AudioRenderer will use
    Sink::Sink& sink;
    /// The streams which will receive the processed samples
    std::array<Sink::SinkStream*, MaxRendererSessions> streams;
};

} // namespace AudioRenderer::ADSP
} // namespace AudioCore